// ImageProcYApp.cpp : Defines the entry point for the console application.
#include "stdafx.h"
//-------------------------------------------------------------------------------------------------
//ImageProcSampleApp.cpp  -  entry point for the console application to exercise ImageProcSample.dll - a simple library used by ImageCurator          
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2012 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Apr 2012
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
#include "ImageProcOpenCVLib.h"
#include "IResize.h"
#include "IAbsDiff.h"
#include "ImageProcSteps.h"
//#include "cfixcc.h"
#include <string>

//OpenCV libs
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv/cv.h"

int ImageProcGetLibApi()
{	
	int rc = 0;
	//ImageProcOpenCVLib lib;

	//ImageProcStepLibAuto *api = lib.GetLibApi();
	//if ( (lib.IsApiValid() == false) || (api == '\0'))
	//{
	//	std::cout << "ERROR: ImageProcOpenCVLib is invalid - do not use this library!" << "\n";
	//	rc = 1;
	//}
	//else
	//{
	//	//Standard console output for all DLLs
	//	std::cout << lib.GetLibName() << " " << lib.GetLibVersion() << " Interface v" << lib.GetLibInterfaceVersion()  << "\n";
	//	std::cout << api->GetCopyright()  << "\n";
	//	std::cout << api->GetDescription()  << "\n\n";

	//	const wchar_t *xmlFile = L"ImageProcOpenCVLib.xml";
	//	const wchar_t *ImageProcStepLibDir = L"c:\\Wills\\Bin";

	//	char buff[ImageExptLib::MaxFileNameLen+1];
	//	std::string filename("[bad]");
	//	if ( ImageExptLib::CreateDefaultImageExptFile(xmlFile, api->GetAuthor()) == false)
	//	{
	//		std::cout << "ERROR: unable to create " << ImageExptLib::ConvertwStrToStr(buff, ImageExptLib::MaxFileNameLen, xmlFile, ImageExptLib::MaxFileNameLen) << "\n";
	//		rc = 1;
	//	}
	//	else
	//	{
	//		if ( api->SaveLibFunctionDefsToXml(xmlFile, ImageProcStepLibDir) == false)
	//		{
	//			std::cout << "ERROR: unable to write api to " << ImageExptLib::ConvertwStrToStr(buff, ImageExptLib::MaxFileNameLen, xmlFile, ImageExptLib::MaxFileNameLen) << "\n";
	//			rc = 1;
	//		}
	//		else
	//			std::cout << "api written to ImageProcOpenCVLib.xml" << "\n\n\n";
	//	}
	//	std::cout << api->GetSupportSite()  << "\n";
	//}
	return rc;
}

int AppResize()
{
	int rc = 0;
	return rc;
}

int AppAbsDiff(/*const std::string image1, const std::string image2*/)
{
	int rc = 0;

	IResize* _pResize = new IResize();
	ImageProcSteps *_steps = new ImageProcSteps();
	ImageProcStepLibs *_Libs = new ImageProcStepLibs();
	ImageExpt *_ief = '\0';

	bool returnrc;
	returnrc = _Libs->LoadLibs(L"C:\\Wills\\Bin\\");	//Apparently requires cfix.dll?
	std::cout << "LoadLibs?" << std::endl;
	std::cout << "GetLibCount?" << _Libs->GetLibCount() <<std::endl;

	//remember to free the memory at the end
	return rc;
}

int AppBlur()
{
	int rc = 0;
	return rc;
}

int AppGaussian()
{
	int rc = 0;
	return rc;
}

int AppCanny()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp", 0);
			
	cv::Canny(input, output, 1.0, 5.0, 3, 1);

	cv::imwrite("C:\\Wills\\testoutp.bmp", output);

	input.release();
	output.release();
	return rc;

}

int AppAdd()
{
	int rc = 1;

	std::string filename1 = "C:\\Wills\\image.bmp";
	cv::Mat input1 = cv::imread(filename1);	
	if( input1.data == NULL )
		std::cout << "Error: Can not read input file 1" << std::endl;
	else
	{
		cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
		if (input2.data == NULL)
			std::cout << "Error: Can not read input file 2" << std::endl;
		else
		{
			if (input1.cols != input2.cols && input1.rows != input2. rows)
				std::cout << "ERROR: Different image size" << std::endl;
			else
			{	
				cv::Mat output;
				cv::add(input1, input2 , output);


				if( cv::imwrite("C:\\Wills\\testoutp.bmp", output) == true)
				{
					output.release();
					rc = 0;
				}					
			}
			input2.release();
		}	
		input1.release();	
	}
	getchar();
	return rc;
	
}

int AppAddWeighted()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	
	if (input.cols != input2.cols && input.rows != input2. rows)
	{
		std::cout << "ERROR: Different image size" << std::endl;
		//rc = 1;
	}
	else
	{
		double alpha, beta, gamma;
		alpha = 70;
		beta = 100;
		gamma = 10;
		cv::addWeighted(input, alpha, input2, beta, gamma, output);
		cv::imwrite("C:\\Wills\\testoutp.bmp", output);

		input.release();
		input2.release();
		output.release();
	}
	return rc;
}

int AppAddMask()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	cv::Mat mask = cv::imread("C:\\Wills\\mask.bmp", 0);

	//cv::namedWindow("Mask", CV_WINDOW_AUTOSIZE);
	//cv::imshow("Mask", mask);
	//cv::waitKey(0);
	//cv::destroyWindow("Mask");
	

	if (input.cols == input2.cols && input.cols == mask.cols && input.rows == input2. rows  && input.rows == mask.rows)
	{
		cv::add(input, input2, output, mask);

		cv::imwrite("C:\\Wills\\testoutp.bmp", output);
		cv::namedWindow("OP", CV_WINDOW_AUTOSIZE);
		cv::imshow("OP", output);
		cv::waitKey(0);
		cv::destroyWindow("OP");	
		input.release();
		input2.release();
		output.release();
	}
	else
	{
		std::cout << "Check your image and mask dimensions." << std::endl;
		rc = 1;
	}

	return rc;
}

int AppSub()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	
	if (input.cols != input2.cols && input.rows != input2. rows)
	{
		std::cout << "ERROR: Different image size" << std::endl;
		//rc = 1;
	}
	else
	{
		cv::subtract(input, input2 , output);
		cv::imwrite("C:\\Wills\\testoutp.bmp", output);

		input.release();
		input2.release();
		output.release();
	}
	return rc;
}

int AppSubMask()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	cv::Mat mask = cv::imread("C:\\Wills\\mask.bmp", 0);

	//cv::namedWindow("Mask", CV_WINDOW_AUTOSIZE);
	//cv::imshow("Mask", mask);
	//cv::waitKey(0);
	//cv::destroyWindow("Mask");
	

	if (input.cols == input2.cols && input.cols == mask.cols && input.rows == input2. rows  && input.rows == mask.rows)
	{
		cv::subtract(input, input2, output, mask);

		cv::imwrite("C:\\Wills\\testoutp.bmp", output);
		cv::namedWindow("OP", CV_WINDOW_AUTOSIZE);
		cv::imshow("OP", output);
		cv::waitKey(0);
		cv::destroyWindow("OP");	
		input.release();
		input2.release();
		output.release();
	}
	else
	{
		std::cout << "Check your image and mask dimensions." << std::endl;
		rc = 1;
	}

	return rc;
}

int AppDivide()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	
	if (input.cols != input2.cols && input.rows != input2. rows)
	{
		std::cout << "ERROR: Different image size" << std::endl;
		//rc = 1;
	}
	else
	{
		cv::divide(input, input2 , output);
		cv::imwrite("C:\\Wills\\testoutp.bmp", output);

		input.release();
		input2.release();
		output.release();
	}
	return rc;
}

int AppAccumulateWeighted()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat mask = cv::imread("C:\\Wills\\image2.bmp");
	double alpha = 0.0;
	if (input.cols == mask.cols && input.rows == mask. rows)
	{
		cv::accumulateWeighted(input, output, alpha, mask);
		cv::imwrite("C:\\Wills\\testoutp.bmp", output);
	}
	else
		std::cout << "Check image dimensions" <<std::endl;

	input.release();
	mask.release();
	output.release();
	return rc;
}

int AppBitAnd()
{
	int rc = 0;
	cv::Mat output;
	cv::Mat input = cv::imread("C:\\Wills\\image.bmp");	
	cv::Mat input2 = cv::imread("C:\\Wills\\image2.bmp");
	cv::Mat mask = cv::imread("C:\\Wills\\mask.bmp", 0);
	double alpha = 0.0;
	if (input.cols == mask.cols && input.rows == mask. rows)
	{
		cv::bitwise_and(input, input2, output, mask);
		cv::imwrite("C:\\Wills\\testoutp.bmp", output);
	}
	else
		std::cout << "Check image dimensions" <<std::endl;
	input.release();
	input2.release();
	mask.release();
	return rc;
}

int main(int argc, char* argv[])
{	
	int rc = 0;
	std::cout << "****ImageProcOpenCVApp v1.0.0.2 - Calls functions from ImageProcOpenCVLib****" << std::endl;
	//for testing purposes:
	//std::cout << argv[1] << std::endl;
	if (argc != 2)
	{
		std::cout << "Input error. Argument = function name, input1, input2. Eg ImageProcOpenCVApp.exe AbsDiff image1.jpg image2.jpg" << std::cout;
	}
	else 
	{	
		std::string input = argv[1];
		if (input == "default")
			rc = ImageProcGetLibApi();
		else if(input == "AbsDiff")
		{
			//std::string input2 = argv[2];
			//std::string input3 = argv[3];
			rc = AppAbsDiff(/*input2, input3*/);
		}
		else if(input == "resize")
		{
			AppResize();
		}
		else if(input == "blur")
		{
			AppBlur();
		}
		else if (input == "gaussian")
		{
			AppGaussian();
		}
		else if (input == "canny")
		{
			AppCanny();
		}
		else if (input == "add")
		{
			AppAdd();
		}
		else if (input == "addw")
		{
			AppAddWeighted();
		}
		else if (input == "addm")
		{
			AppAddMask();
		}
		else if (input == "sub")
		{
			AppSub();
		}
		else if (input == "subm")
		{
			AppSubMask();
		}
		else if (input == "divide")
		{
			AppDivide();
		}
		else if (input == "divides")
		{
			std::cout<<"divdes"<<std::endl;
		}
		else if (input == "multiply")
		{
			std::cout<<"multiply"<<std::endl;
		}
		else if (input == "accumulatew")
		{
			AppAccumulateWeighted();
		}
		else if (input == "bitand")
		{
			AppBitAnd();
		}
		/*else if (input == "divides")
		{
			break;
		}
		else if (input == "divides")
		{
			break;
		}*/
	}
		

	std::cout << "\n***program ends ok***\n\n";

	return rc;
}

